package main

import (
	"fmt"
	"log"

	"gitcode.com/deyiyangyang/bampoo/evl"
	"gitcode.com/deyiyangyang/bampoo/lex"
	"gitcode.com/deyiyangyang/bampoo/obj"

	"gitcode.com/deyiyangyang/bampoo/par"
)

func main() {
	fmt.Println("=== Bamboo Scheme Define 功能测试 ===")
	fmt.Println()

	// 创建环境和评估器
	env := obj.NewEnvironment()
	evaluator := evl.New(env)

	// 测试用例
	testCases := []struct {
		name    string
		code    string
		wantErr bool
	}{
		{
			name:    "定义整数变量",
			code:    `(define x 42)`,
			wantErr: false,
		},
		{
			name:    "定义字符串变量",
			code:    `(define name "Hello World")`,
			wantErr: false,
		},
		{
			name:    "定义函数",
			code:    `(define add (lambda (x y) (+ x y)))`,
			wantErr: false,
		},
		{
			name:    "定义复杂表达式",
			code:    `(define result (+ 10 (* 5 3)))`,
			wantErr: false,
		},
		{
			name:    "使用已定义的变量",
			code:    `(define x 100) (+ x 50)`,
			wantErr: false,
		},
		{
			name:    "调用已定义的函数",
			code:    `(define square (lambda (n) (* n n))) (square 5)`,
			wantErr: false,
		},
	}

	for _, tc := range testCases {
		fmt.Printf("测试: %s\n", tc.name)
		fmt.Printf("代码: %s\n", tc.code)

		// 词法分析和语法分析
		lexer := lex.New(tc.code)
		parser := par.New(lexer)
		program := parser.ParseProgram()

		// 检查语法分析器的错误
		parserErrors := parser.Errors()
		if len(parserErrors) > 0 && !tc.wantErr {
			for _, e := range parserErrors {
				log.Printf("语法分析错误: %v", e)
			}
			continue
		}

		// 评估表达式
		fmt.Printf("结果: ")
		result, err := evaluator.Eval(program)
		if err != nil {
			if !tc.wantErr {
				log.Printf("评估错误: %v", err)
			}
			continue
		}

		switch v := result.(type) {
		case *obj.IntegerValue:
			fmt.Printf("%d", v.Value)
		case *obj.StringValue:
			fmt.Printf("\"%s\"", v.Value)
		case *obj.FunctionValue:
			fmt.Printf("#<function:%s>", v.Type())
		case *obj.NilValue:
			fmt.Printf("nil")
		default:
			fmt.Printf("%v", result)
		}
		fmt.Println("\n---")
	}

	fmt.Println("\n=== 环境内容 ===")
	fmt.Printf("当前环境: %s\n", env)

	// 测试一些交互式命令
	fmt.Println("\n=== 交互式测试 ===")
	fmt.Println("你可以输入以下命令来测试define功能:")
	fmt.Println("1. (define my-var 123)")
	fmt.Println("2. (define greet \"Hello, Scheme!\")")
	fmt.Println("3. (define double (lambda (x) (* x 2)))")
	fmt.Println("4. (double 21)")
	fmt.Println("5. (+ my-var 100)")
}
